Skip to content

fix(openai): recover from Gemini-style concatenated JSON tool call arguments in streaming#7549

Open
r266-tech wants to merge 2 commits intomicrosoft:mainfrom
r266-tech:fix/gemini-streaming-tool-args-6843
Open

fix(openai): recover from Gemini-style concatenated JSON tool call arguments in streaming#7549
r266-tech wants to merge 2 commits intomicrosoft:mainfrom
r266-tech:fix/gemini-streaming-tool-args-6843

Conversation

@r266-tech
Copy link
Copy Markdown

Summary

Fixes #6843openai.BadRequestError when using Gemini models with model_client_stream=True and multiple tool calls.

Root cause

Some providers (notably Gemini) emit a complete JSON object per streaming chunk rather than incremental argument deltas:

Chunk delta.function.arguments
1 {} (empty placeholder)
2 {"stock": "MSFT"} (actual arguments)

Simple string concatenation then produces {}{"stock":"MSFT"} — invalid JSON — which fails when the agent tries to call the tool.

Fix

After the streaming loop finishes, validate each accumulated FunctionCall.arguments with json.loads. If it fails, walk backwards through the string to find the last valid complete JSON object (bracket-depth scan) and use that as the canonical arguments value.

This is a surgical, provider-neutral recovery step that does not change the normal (non-Gemini) streaming path.

Changes

  • python/packages/autogen-ext/src/autogen_ext/models/openai/_openai_client.py: add recovery step in create_stream before building CreateResult
  • python/packages/autogen-ext/tests/models/test_openai_model_client.py: add test_tool_calling_with_stream_gemini_style_arguments regression test

Test

New test simulates Gemini's two-chunk pattern ({} then {"input": "task"}) and asserts that the recovered arguments are {"input": "task"} (the last valid complete JSON object).

🤖 Generated with Claude Code

…guments

When using Gemini (or other providers that emit a complete JSON object per
streaming chunk rather than incremental deltas), simple string concatenation
produces invalid JSON such as `{}{{"stock":"MSFT"}}`.

Detect and recover by keeping only the last valid complete JSON object in the
accumulated arguments string, using a backwards bracket-depth scan.

Fixes microsoft#6843
…call arguments

Adds test_tool_calling_with_stream_gemini_style_arguments which simulates
Gemini's behavior of sending a complete empty JSON object in the first chunk
followed by the real arguments in a second chunk.

Related to fix for microsoft#6843
@r266-tech
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multiple tool call failure with Gemini

1 participant